package com.ara.websocket;

import android.text.TextUtils;
import android.util.Log;

import com.ara.websocket.listener.ConnectCallback;

import org.java_websocket.handshake.ServerHandshake;

import java.net.URI;

/**
 * Created by XieXin on 2021/7/5.
 * WebSocket客户端
 */
public final class XWebSocketClient {
    private static final String TAG = XWebSocketClient.class.getSimpleName();

    private BaseWebSocketClient client;
    private URI serverUri;
    private ConnectCallback callback;

    private static class Client {
        private final static XWebSocketClient instance = new XWebSocketClient();

        public static XWebSocketClient getInstance() {
            return instance;
        }
    }

    public static void init(String serverUrl) {
        Client.getInstance().serverUri = URI.create(serverUrl);
    }

    public static XWebSocketClient connect(ConnectCallback callback) {
        Client.getInstance().callback = callback;
        Client.getInstance().connectServer();
        return Client.getInstance();
    }

    private void connectServer() {
        try {
            if (client == null) {
                client = new BaseWebSocketClient(serverUri) {
                    @Override
                    public void onMessage(String message) {
                        super.onMessage(message);
                        if (callback != null) callback.onMessage(message);
                    }

                    @Override
                    public void onOpen(ServerHandshake serverHandshake) {
                        super.onOpen(serverHandshake);
                        if (callback != null)
                            callback.onConnectSuccess(
                                    serverHandshake.getHttpStatus(),
                                    serverHandshake.getHttpStatusMessage()
                            );
                    }

                    @Override
                    public void onClose(int code, String reason, boolean remote) {
                        super.onClose(code, reason, remote);
                        if (callback != null) callback.onClose(code, reason, remote);
                    }

                    @Override
                    public void onError(Exception ex) {
                        super.onError(ex);
                        if (callback != null) callback.onError(ex);
                    }
                };
                client.connectBlocking();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
            Log.e(TAG, "connect onError ex=" + e.getMessage());
            if (callback != null) callback.onError(e);
        }
    }

    /**
     * 是否连接
     */
    private boolean isOpenWebSocket() {
        if (client == null) return true;
        return client.isOpen();
    }

    /**
     * 是否关闭
     */
    private boolean isCloseWebSocket() {
        if (client == null) return true;
        return client.isClosed();
    }

    /**
     * 是否Client为空
     */
    private boolean isClientEmpty() {
        return client == null;
    }

    /**
     * 重连WebSocket
     */
    private void reconnectionWebSocket() {
        if (client != null) {
            synchronized (XWebSocketClient.class) {
                try {
                    if (client != null) client.reconnectBlocking();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    Log.e(TAG, e.getMessage());
                }
            }
        } else {
            Log.e(TAG, "send client error null");
        }
    }

    /**
     * 断开连接
     */
    private void closeConnection() {
        Log.d(TAG, "close connect");

        try {
            if (null != client) client.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            client = null;
        }
    }

    public static void close() {
        Client.getInstance().closeConnection();
    }

    public static void reconnection() {
        Client.getInstance().reconnectionWebSocket();
    }

    public static boolean isEmpty() {
        return Client.getInstance().isClientEmpty();
    }

    public static boolean isClose() {
        return Client.getInstance().isCloseWebSocket();
    }

    public static boolean isOpen() {
        return Client.getInstance().isOpenWebSocket();
    }

    /**
     * 发送消息
     *
     * @param message String
     */
    public static void sendMessage(String message) {
        if (TextUtils.isEmpty(message)) {
            Log.e(TAG, "Message sending cannot null ");
            return;
        }
        Client.getInstance().send(message);
    }

    /**
     * 发送消息
     *
     * @param message String
     */
    private void send(String message) {
        Log.i(TAG, "send message: " + message);

        if (client != null && client.isOpen()) {
            client.send(message);
        } else {
            Log.e(TAG, "send client error null");
        }
    }

}
